﻿using DoNet.ApiHttpClient;
using DoNet.Common.Helpers;
using DoNet.Wechat.MP.Common.Entitys;
using Microsoft.Extensions.Logging;

namespace DoNet.Wechat.MP.Common
{
    /// <summary>
    /// 微信公众平台公共接口类
    /// </summary>
    public class CommonApi : WechatMpBase
    {
        /// <summary>
        /// 微信公众平台公共接口类
        /// </summary>
        /// <param name="provider"></param>
        public CommonApi(ILogger logger, IServiceProvider provider) : base(logger, provider)
        {

        }

        /// <summary>
        /// 全局唯一后台接口调用凭据（access_token）。调用绝大多数后台接口时都需使用 access_token，开发者需要进行妥善保存。
        /// </summary>
        /// <param name="appid">第三方用户唯一凭证</param>
        /// <param name="secret">第三方用户唯一凭证密钥，即appsecret</param>
        /// <param name="grant_type">获取access_token填写client_credential</param>
        /// <returns></returns>
        public AccessTokenResult? GetToken(string appid, string secret, string grant_type = "client_credential")
        {
            try
            {
                if (wechatApiService != null)
                {
                    Dictionary<string, object> param = new Dictionary<string, object>();
                    param.Add("appid", appid);
                    param.Add("secret", secret);
                    param.Add("grant_type", grant_type);

                    var response = wechatApiService.SendRequest(HttpMethod.Get, "cgi-bin/token", param);
                    HttpClientResponse httpClientResponse = new HttpClientResponse(response);
                    httpClientResponse.GetResponseBody();
                    if (httpClientResponse.IsResponse)
                    {
                        if (!string.IsNullOrWhiteSpace(httpClientResponse.ResponseBody))
                        {
                            var returnData = JsonHelper.DeserializeObject<AccessTokenResult>(httpClientResponse.ResponseBody);
                            if (returnData != null)
                            {
                                if (returnData.errcode == 0)
                                {
                                    var expires_in = returnData.expires_in;
                                    returnData.expire_time = DateTime.Now.Add(TimeSpan.FromSeconds(expires_in - 30)); //提前30秒过期
                                }
                                return returnData;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
            return null;
        }

        /// <summary>
        /// 获取调用微信JS接口的临时票据
        /// </summary>
        /// <param name="access_token">接口调用凭证</param>
        /// <param name="type">默认为jsapi，当作为卡券接口使用时，应当为wx_card</param>
        /// <returns></returns>
        public JsApiTicketResult? GetJsApiTicket(string access_token, string type = "jsapi")
        {
            try
            {
                if (wechatApiService != null)
                {
                    Dictionary<string, object> param = new Dictionary<string, object>();
                    param.Add("access_token", access_token);
                    param.Add("type", type);

                    var response = wechatApiService.SendRequest(HttpMethod.Get, "cgi-bin/ticket/getticket", param);
                    HttpClientResponse httpClientResponse = new HttpClientResponse(response);
                    httpClientResponse.GetResponseBody();
                    if (httpClientResponse.IsResponse)
                    {
                        if (!string.IsNullOrWhiteSpace(httpClientResponse.ResponseBody))
                        {
                            var returnData = JsonHelper.DeserializeObject<JsApiTicketResult>(httpClientResponse.ResponseBody);
                            if (returnData != null)
                            {
                                return returnData;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
            return null;
        }

        #region 获取微信服务器的ip段
        /// <summary>
        /// 获取微信API接口 IP地址
        /// </summary>
        /// <param name="access_token">接口调用凭证</param>
        /// <returns></returns>
        public GetCallBackIpResult? GetApiDomainIp(string access_token)
        {
            try
            {
                if (wechatApiService != null)
                {
                    Dictionary<string, object> param = new Dictionary<string, object>();
                    param.Add("access_token", access_token);

                    var response = wechatApiService.SendRequest(HttpMethod.Get, "cgi-bin/get_api_domain_ip", param);
                    HttpClientResponse httpClientResponse = new HttpClientResponse(response);
                    httpClientResponse.GetResponseBody();
                    if (httpClientResponse.IsResponse)
                    {
                        if (!string.IsNullOrWhiteSpace(httpClientResponse.ResponseBody))
                        {
                            var returnData = JsonHelper.DeserializeObject<GetCallBackIpResult>(httpClientResponse.ResponseBody);
                            if (returnData != null)
                            {
                                return returnData;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
            return null;
        }

        /// <summary>
        /// 获取微信callback IP地址
        /// </summary>
        /// <param name="access_token">接口调用凭证</param>
        /// <returns></returns>
        public GetCallBackIpResult? GetCallBackIp(string access_token)
        {
            try
            {
                if (wechatApiService != null)
                {
                    Dictionary<string, object> param = new Dictionary<string, object>();
                    param.Add("access_token", access_token);

                    var response = wechatApiService.SendRequest(HttpMethod.Get, "cgi-bin/getcallbackip", param);
                    HttpClientResponse httpClientResponse = new HttpClientResponse(response);
                    httpClientResponse.GetResponseBody();
                    if (httpClientResponse.IsResponse)
                    {
                        if (!string.IsNullOrWhiteSpace(httpClientResponse.ResponseBody))
                        {
                            var returnData = JsonHelper.DeserializeObject<GetCallBackIpResult>(httpClientResponse.ResponseBody);
                            if (returnData != null)
                            {
                                return returnData;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
            return null;
        }
        #endregion

        /// <summary>
        /// 网络检测
        /// 为了帮助开发者排查回调连接失败的问题，提供这个网络检测的API。它可以对开发者URL做域名解析，然后对所有IP进行一次ping操作，得到丢包率和耗时。
        /// </summary>
        /// <param name="access_token">接口调用凭证</param>
        /// <param name="action">执行的检测动作，允许的值：dns（做域名解析）、ping（做ping检测）、all（dns和ping都做）</param>
        /// <param name="check_operator">指定平台从某个运营商进行检测，允许的值：CHINANET（电信出口）、UNICOM（联通出口）、CAP（腾讯自建出口）、DEFAULT（根据ip来选择运营商）</param>
        /// <returns></returns>
        public CallBackCheckResult? CallBackCheck(string access_token, string action, string check_operator)
        {
            try
            {
                if (wechatApiService != null)
                {
                    Dictionary<string, object> param = new Dictionary<string, object>();
                    param.Add("action", action);
                    param.Add("check_operator", check_operator);

                    var response = wechatApiService.SendRequest(HttpMethod.Post, $"cgi-bin/callback/check?access_token={access_token}", param);
                    HttpClientResponse httpClientResponse = new HttpClientResponse(response);
                    httpClientResponse.GetResponseBody();
                    if (httpClientResponse.IsResponse)
                    {
                        if (!string.IsNullOrWhiteSpace(httpClientResponse.ResponseBody))
                        {
                            var returnData = JsonHelper.DeserializeObject<CallBackCheckResult>(httpClientResponse.ResponseBody);
                            if (returnData != null)
                            {
                                return returnData;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
            return null;
        }

        /// <summary>
        ///公众号调用或第三方平台帮公众号调用对公众号的所有api调用（包括第三方帮其调用）次数进行清零
        /// </summary>
        /// <param name="access_token">接口调用凭证</param>
        /// <param name="appId"></param>
        /// <returns></returns>
        public JsonResult? Clear_quota(string access_token, string appId)
        {
            try
            {
                if (wechatApiService != null)
                {
                    Dictionary<string, object> param = new Dictionary<string, object>();
                    param.Add("appid", appId);

                    var response = wechatApiService.SendRequest(HttpMethod.Post, $"cgi-bin/clear_quota?access_token={access_token}", param);
                    HttpClientResponse httpClientResponse = new HttpClientResponse(response);
                    httpClientResponse.GetResponseBody();
                    if (httpClientResponse.IsResponse)
                    {
                        if (!string.IsNullOrWhiteSpace(httpClientResponse.ResponseBody))
                        {
                            var returnData = JsonHelper.DeserializeObject<JsonResult>(httpClientResponse.ResponseBody);
                            if (returnData != null)
                            {
                                return returnData;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
            return null;
        }
    }
}
